#include <CODEPORTS/swap.h>
#include "codeports.h"
#include <stdlib.h>
#include <string.h>

void
SWP_Init(void)
{
	gl_setcontextvgavirtual(video.mode.code);
	video.mode.swap = gl_allocatecontext();
	gl_getcontext(video.mode.swap);
	gl_setcontext(video.mode.swap);

	switch(video.mode.swap->bytesperpixel)
	{
		case 1:
		{
			SWP_SetPixelRGB = SWP_SetPixelRGB8;
			SWP_GetPixelRGB = SWP_GetPixelRGB8;
			SWP_SetBoxRGB = SWP_SetBoxRGB8;
			SWP_SetBox = SWP_SetBoxRGB8;
			BOX_SetPixelRGB = BOX_SetPixelRGB8;
			BOX_GetPixelRGB = BOX_GetPixelRGB8;
			break;
		}
		case 2:
		{
			SWP_SetPixelRGB = SWP_SetPixelRGB16;
			SWP_GetPixelRGB = SWP_GetPixelRGB16;
			SWP_SetBoxRGB = SWP_SetBoxRGB16;
			SWP_SetBox = SWP_SetBoxRGB16;
			BOX_SetPixelRGB = BOX_SetPixelRGB16;
			BOX_GetPixelRGB = BOX_GetPixelRGB16;
			break;
		}
		case 3:
		{
			SWP_SetPixelRGB = SWP_SetPixelRGB24;
			SWP_GetPixelRGB = SWP_GetPixelRGB24;
			SWP_SetBoxRGB = SWP_SetBoxRGB24;
			SWP_SetBox = SWP_SetBoxRGB24;
			BOX_SetPixelRGB = BOX_SetPixelRGB24;
			BOX_GetPixelRGB = BOX_GetPixelRGB24;
			break;
		}
		case 4:
		{
			SWP_SetPixelRGB = SWP_SetPixelRGB32;
			SWP_GetPixelRGB = SWP_GetPixelRGB32;
			SWP_SetBoxRGB = SWP_SetBoxRGB32;
			SWP_SetBox = SWP_SetBoxRGB32;
			BOX_SetPixelRGB = BOX_SetPixelRGB32;
			BOX_GetPixelRGB = BOX_GetPixelRGB32;
			break;
		}
	}
}

void
SWP_Final(void)
{
	gl_freecontext(video.mode.swap);
}

void
SWP_GetSize(int *width, int *height)
{
	*width = video.mode.swap->width;
	*height = video.mode.swap->height;
}

void
SWP_GetDepth(int *depth)
{
	*depth = video.mode.swap->bytesperpixel;
}

void
SWP_Clear(void)
{
	//memset(video.swap, 0, video.mode.fixed.smem_len);
	gl_clearscreen(0);
	/*
	unsigned int i, j;
	for(j = 0; j < video.mode.swap->height; j++)
	{
		for(i = 0; i < video.mode.swap->width; i++)
		{
			switch(video.mode.swap->bytesperpixel)
			{
				case 1:
				{
					//SWP_SetPixelColor(i, j, 0);
					SWP_SetPixelRGB8(i, j, 0, 0, 0);
					break;
				}
				case 2:
				{
					SWP_SetPixelRGB16(i, j, 0, 0, 0);
					break;
				}
				case 3:
				{
					SWP_SetPixelRGB24(i, j, 0, 0, 0);
					break;
				}
				case 4:
				{
					SWP_SetPixelRGBA(i, j, 0, 0, 0, 0);
					break;
				}
			}
		}
	}
	*/
}

void
SWP_Screen(void)
{
	//vga_waitretrace();
	gl_copyscreen(video.mode.screen);
	//usleep(10000);
}

void
SWP_SetPixelColor(int x, int y, unsigned char c)
{
	if(0 <= x && x < video.mode.swap->width && 0 <= y && y < video.mode.swap->height)
		gl_setpixel(x, y, c);
}

void
SWP_SetPixelRGB8(int x, int y, unsigned char r, unsigned char g, unsigned char b)
{
	if(0 <= x && x < video.mode.swap->width && 0 <= y && y < video.mode.swap->height)
		gl_setpixelrgb(x, y, r, g, b);
}

void
SWP_SetPixelRGB16(int x, int y, unsigned char r, unsigned char g, unsigned char b)
{
	if(0 <= x && x < video.mode.swap->width && 0 <= y && y < video.mode.swap->height)
		gl_setpixelrgb(x, y, r, g, b);
}

void
SWP_SetPixelRGB24(int x, int y, unsigned char r, unsigned char g, unsigned char b)
{
	if(0 <= x && x < video.mode.swap->width && 0 <= y && y < video.mode.swap->height)
		gl_setpixelrgb(x, y, r, g, b);
}

void
SWP_SetPixelRGB32(int x, int y, unsigned char r, unsigned char g, unsigned char b)
{
	if(0 <= x && x < video.mode.swap->width && 0 <= y && y < video.mode.swap->height)
		gl_setpixelrgb(x, y, r, g, b);
}

void
SWP_SetPixelRGBA(int x, int y, unsigned char r, unsigned char g, unsigned char b, unsigned char a)
{
	if(0 <= x && x < video.mode.swap->width && 0 <= y && y < video.mode.swap->height)
		gl_setpixelrgb(x, y, r, g, b);
}

void
SWP_GetPixelColor(int x, int y, unsigned char *c)
{
	if(0 <= x && x < video.mode.swap->width && 0 <= y && y < video.mode.swap->height)
		*c = gl_getpixel(x, y);
}

void
SWP_GetPixelRGB8(int x, int y, unsigned char *r, unsigned char *g, unsigned char *b)
{
	if(0 <= x && x < video.mode.swap->width && 0 <= y && y < video.mode.swap->height)
	{
		unsigned char c = gl_getpixel(x, y);
		*r = ((c & 0xC0) >> 6) << 6;
		*g = ((c & 0x38) >> 3) << 5;
		*b = (c & 0x07) << 5;
	}
}

void
SWP_GetPixelRGB16(int x, int y, unsigned char *r, unsigned char *g, unsigned char *b)
{
	if(0 <= x && x < video.mode.swap->width && 0 <= y && y < video.mode.swap->height)
		gl_getpixelrgb(x, y, (int *) r, (int *) g, (int *) b);
}

void
SWP_GetPixelRGB24(int x, int y, unsigned char *r, unsigned char *g, unsigned char *b)
{
	if(0 <= x && x < video.mode.swap->width && 0 <= y && y < video.mode.swap->height)
		gl_getpixelrgb(x, y, (int *) r, (int *) g, (int *) b);
}

void
SWP_GetPixelRGB32(int x, int y, unsigned char *r, unsigned char *g, unsigned char *b)
{
	if(0 <= x && x < video.mode.swap->width && 0 <= y && y < video.mode.swap->height)
		gl_getpixelrgb(x, y, (int *) r, (int *) g, (int *) b);
}

void
SWP_GetPixelRGBA(int x, int y, unsigned char *r, unsigned char *g, unsigned char *b, unsigned char *a)
{
	if(0 <= x && x < video.mode.swap->width && 0 <= y && y < video.mode.swap->height)
		gl_getpixelrgb(x, y, (int *) r, (int *) g, (int *) b);
}

/*
void
SWP_SetBoxColor(int x, int y, BOX *box)
{
	unsigned int i, j;
	unsigned char c;
	for(j = 0; j < box->info.height; j++)
	{
		for(i = 0; i < box->info.width; i++)
		{
			BOX_GetPixelColor(box, i, j, &c);
			SWP_SetPixelColor(x + i, y + j, c);
		}
	}
}

void
SWP_SetBoxRGB8(int x, int y, BOX *box)
{
	unsigned int i, j;
	unsigned char r, g, b;
	for(j = 0; j < box->info.height; j++)
	{
		for(i = 0; i < box->info.width; i++)
		{
			BOX_GetPixelRGB8(box, i, j, &r, &g, &b);
			SWP_SetPixelRGB8(x + i, y + j, r, g, b);
		}
	}
}

void
SWP_SetBoxRGB16(int x, int y, BOX *box)
{
	unsigned int i, j;
	unsigned char r, g, b;
	for(j = 0; j < box->info.height; j++)
	{
		for(i = 0; i < box->info.width; i++)
		{
			BOX_GetPixelRGB16(box, i, j, &r, &g, &b);
			SWP_SetPixelRGB16(x + i, y + j, r, g, b);
		}
	}
}

void
SWP_SetBoxRGB24(int x, int y, BOX *box)
{
	unsigned int i, j;
	unsigned char r, g, b;
	for(j = 0; j < box->info.height; j++)
	{
		for(i = 0; i < box->info.width; i++)
		{
			BOX_GetPixelRGB24(box, i, j, &r, &g, &b);
			SWP_SetPixelRGB24(x + i, y + j, r, g, b);
		}
	}
}

void
SWP_SetBoxRGB32(int x, int y, BOX *box)
{
	unsigned int i, j;
	unsigned char r, g, b;
	for(j = 0; j < box->info.height; j++)
	{
		for(i = 0; i < box->info.width; i++)
		{
			BOX_GetPixelRGB32(box, i, j, &r, &g, &b);
			SWP_SetPixelRGB32(x + i, y + j, r, g, b);
		}
	}
}

void
SWP_SetBoxRGBA(int x, int y, BOX *box)
{
	unsigned int i, j;
	unsigned char r, g, b, a;
	for(j = 0; j < box->info.height; j++)
	{
		for(i = 0; i < box->info.width; i++)
		{
			BOX_GetPixelRGBA(box, i, j, &r, &g, &b, &a);
			SWP_SetPixelRGBA(x + i, y + j, r, g, b, a);
		}
	}
}

void
SWP_SetImage(char *image)
{
	MagickWand *mw;
	unsigned char *buffer;
	unsigned int i, j;
	buffer = malloc(video.mode.swap->width * video.mode.swap->height * 4);
	mw = NewMagickWand();
	MagickReadImage(mw, image);
	if(video.mode.swap->width != MagickGetImageWidth(mw) || video.mode.swap->height != MagickGetImageHeight(mw))
		MagickScaleImage(mw, video.mode.swap->width, video.mode.swap->height);
	MagickExportImagePixels(mw, 0, 0, video.mode.swap->width, video.mode.swap->height, "RGBA", CharPixel, buffer);
	DestroyMagickWand(mw);
	for(j = 0; j < video.mode.swap->height; j++)
	{
		for(i = 0; i < video.mode.swap->width; i++)
		{
			switch(video.mode.swap->bytesperpixel)
			{
				case 1:
				{
					//SWP_SetPixelColor(i, j, buffer[(j * video.mode.swap->width + i) * 4]);
					SWP_SetPixelRGB8(i, j, buffer[(j * video.mode.swap->width + i) * 4 + 0], buffer[(j * video.mode.swap->width + i) * 4 + 1] , buffer[(j * video.mode.swap->width + i) * 4 + 2]);
					break;
				}
				case 2:
				{
					SWP_SetPixelRGB16(i, j, buffer[(j * video.mode.swap->width + i) * 4 + 0], buffer[(j * video.mode.swap->width + i) * 4 + 1] , buffer[(j * video.mode.swap->width + i) * 4 + 2]);
					break;
				}
				case 3:
				{
					SWP_SetPixelRGB24(i, j, buffer[(j * video.mode.swap->width + i) * 4 + 0], buffer[(j * video.mode.swap->width + i) * 4 + 1] , buffer[(j * video.mode.swap->width + i) * 4 + 2]);
					break;
				}
				case 4:
				{
					SWP_SetPixelRGBA(i, j, buffer[(j * video.mode.swap->width + i) * 4 + 0], buffer[(j * video.mode.swap->width + i) * 4 + 1] , buffer[(j * video.mode.swap->width + i) * 4 + 2], buffer[(j * video.mode.swap->width + i) * 4 + 3]);
					break;
				}
			}
		}
	}
	free(buffer);
}

void
SWP_GetImage(char *image)
{
	MagickWand *mw;
	unsigned char *buffer;
	unsigned int i, j;
	unsigned char r, g, b, a;
	buffer = malloc(video.mode.swap->width * video.mode.swap->height * 4);
	for(j = 0; j < video.mode.swap->height; j++)
	{
		for(i = 0; i < video.mode.swap->width; i++)
		{
			switch(video.mode.swap->bytesperpixel)
			{
				case 1:
				{
					//SWP_GetPixelColor(i, j, &c);
					SWP_GetPixelRGB8(i, j, &r, &g, &b);
					buffer[(j * video.mode.swap->width + i) * 4 + 0] = r;
					buffer[(j * video.mode.swap->width + i) * 4 + 1] = g;
					buffer[(j * video.mode.swap->width + i) * 4 + 2] = b;
					buffer[(j * video.mode.swap->width + i) * 4 + 3] = 0;
					break;
				}
				case 2:
				{
					SWP_GetPixelRGB16(i, j, &r, &g, &b);
					buffer[(j * video.mode.swap->width + i) * 4 + 0] = r;
					buffer[(j * video.mode.swap->width + i) * 4 + 1] = g;
					buffer[(j * video.mode.swap->width + i) * 4 + 2] = b;
					buffer[(j * video.mode.swap->width + i) * 4 + 3] = 0;
					break;
				}
				case 3:
				{
					SWP_GetPixelRGB24(i, j, &r, &g, &b);
					buffer[(j * video.mode.swap->width + i) * 4 + 0] = r;
					buffer[(j * video.mode.swap->width + i) * 4 + 1] = g;
					buffer[(j * video.mode.swap->width + i) * 4 + 2] = b;
					buffer[(j * video.mode.swap->width + i) * 4 + 3] = 0;
					break;
				}
				case 4:
				{
					SWP_GetPixelRGBA(i, j, &r, &g, &b, &a);
					buffer[(j * video.mode.swap->width + i) * 4 + 0] = r;
					buffer[(j * video.mode.swap->width + i) * 4 + 1] = g;
					buffer[(j * video.mode.swap->width + i) * 4 + 2] = b;
					buffer[(j * video.mode.swap->width + i) * 4 + 3] = a;
					break;
				}
			}
		}
	}
	mw = NewMagickWand();
	MagickConstituteImage(mw, video.mode.swap->width, video.mode.swap->height, "RGBO", CharPixel, buffer);
	free(buffer);
	MagickWriteImage(mw, image);
	DestroyMagickWand(mw);
}
*/
